package com.example.pool.httpTest.util;

// 同步http工具类
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

/**
 * https://blog.csdn.net/cckevincyh/article/details/129322877
 */
public class HttpClientUtil {
    // 首先我们知道HTTP连接需要经过三次握手，四次挥手的过程，这是很耗费性能的；所以HTTP连接池帮助我们节省了这一步，提高了吞吐量。
    public static CloseableHttpClient getHttpClient() {
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(15000) // 客户端等待服务端返回数据的超时时间
                .setConnectTimeout(5000) // 确定连接建立之前的超时时间(以毫秒为单位)。也就是客户端发起TCP连接请求的超时时间，一般也就是TCP三次握手的时间
                .setConnectionRequestTimeout(50000) // 从连接管理器请求连接时使用的超时时间(以毫秒为单位)
                .build();
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("HTTP", new PlainConnectionSocketFactory())
//                .register("https", new SSLIOSessionStrategy(sslcontext, new AllowAllHostnameVerifier()))
                .build();
        /**
         * 在HttpClient 4.3以后增加了PoolingHttpClientConnectionManager连接池来管理持有连接，同一条TCP链路上，连接是可以复用的。
         * HttpClient通过连接池的方式进行连接持久化（所以它这个连接池其实是tcp的连接池。它里面有一个很重要的概念：Route的概念，代表一条线路。
         * 比如baidu.com是一个route，163.com是一个route…）。
         * 连接池：可能是http请求，也可能是https请求
         * 加入池话技术，就不用每次发起请求都新建一个连接（每次连接握手三次，效率太低）
         */
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        // 连接池中最大连接数(总路由数)
        connectionManager.setMaxTotal(10);
        // 分配给同一个route(路由)最大的并发连接数,route为运行环境机器到目标机器的一条线路,举例来说,我们使用HttpClient的实现来分别请求
        // www.baidu.com 的资源和 www.bing.com 的资源那么他就会产生两个route;
        connectionManager.setDefaultMaxPerRoute(1000);
        connectionManager.setValidateAfterInactivity(500);
        /**
         * 在HttpClientBuilder( HttpClients.custom() )中也可以设置这两个参数，分别是setMaxConnPerRoute和setMaxConnTotal。
         * 但是他们都会被PoolingHttpClientConnectionManager中设置的覆盖
         */
        return HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .setConnectionManagerShared(true)
                .build();
    }
}